#include <sstream>
#include <iostream>
#include "RecursiveDescentParser.h"
#include "FunctionEntry.h"

/**
 * Contructor takes a pointer to a ScannerInterface
 */
RecursiveDescentParser::RecursiveDescentParser(ScannerInterface* si) {
	scanner=si;
	errorCount=0;
	errorCondition=false;
	
	symTab.registerObserver( &iCode );
	codeGenerator =  new MoonGenerator( si->getFilename(), &iCode );
}

/**
 * Destructor
 */
RecursiveDescentParser::~RecursiveDescentParser() {
	delete codeGenerator;
}

/**
 * Public function which begins the parsing
 */
void RecursiveDescentParser::start() {
	token = scanner->getToken();
	prg();

#if DEBUG_PARSER
	if(errorCondition) {
		std::cout << "Parsing did not complete successfully." << std::endl;
	} else {
		std::cout << "Parsing completed successfully!" << std::endl;
	}
#endif
	
	if( errorCount == 0 ) { // don't attempt to generate target code unless everything went well
		codeGenerator->setCharacterConsts( litTab.getCharacterConstants() );
		codeGenerator->setNumericalConsts( litTab.getNumericalConstants() );
		codeGenerator->generateTargetCode();
	}
}

/**
 * The Error handlers
 */
void RecursiveDescentParser::errorHandler() {
	errorCount++;
	errorCondition=true;
	/*
	std::stringstream errorMsg;
	errorMsg << "Line " << token.getLineNum() << ": Parsing error near " << token;
	std::cout << errorMsg.str() << "\n";
	notifyErrorObservers(errorMsg.str());
	*/
}

void RecursiveDescentParser::errorHandler(std::string errorMessage, Token tk, bool recoverable) {
	errorHandler(errorMessage, tk.getLineNum(), recoverable);
}

void RecursiveDescentParser::errorHandler(std::string errorMessage, int lineNumber, bool recoverable) {
	errorCount++;
	if(!errorCondition && !recoverable) {
		errorCondition=true;
	}
	std::stringstream errorMsg;
	errorMsg << "Line " << lineNumber << ": " << errorMessage;
	notifyErrorObservers(errorMsg.str());
}

/**
 * Return the state of errorCondition
 */
bool RecursiveDescentParser::getError() {
	return errorCondition;
}

/**
 * Compare the current token to the supplied token type. 
 * If it matches, get the next token from the scanner else
 * set errorCondition to true
 * @param TokenType
 */
void RecursiveDescentParser::match(TokenType tkType) {
	if(token == tkType) {
		token = scanner->getToken();
	} else{
		errorHandler();
	}
}

void RecursiveDescentParser::matchParameters(FunctionEntry* fEntry, ParamList* &callerParams, Token tk) {
	if(fEntry->getEntryType()!=TableEntry::FUNCTION) return;
	
	int paramCount = 1;
	ParamList* declParams = fEntry->getParamaterList();
	
	ParamList::iterator j=callerParams->begin();

	for(ParamList::iterator i=declParams->begin();
		i!=declParams->end();
		++i)
	{
		if(j==callerParams->end()) {
			std::stringstream errorMsg;
			errorMsg << "Function '" << fEntry->getName() << "' does not take " 
				<< paramCount-1 << " parameter(s)";
			errorHandler(errorMsg.str(), tk);
			return;
		}
		
		if((*i)->getType() != (*j)->getType()) {
			std::stringstream errorMsg;
			errorMsg << "Parameter " << paramCount << " should be of type " 
				<< (((*i)->getType()==T_INT)? "'int'" : "'char'");
			errorHandler(errorMsg.str(), tk);
		} 
		
		if((*i)->getAttribute() != (*j)->getAttribute()) {
			std::stringstream errorMsg;
			errorMsg << "Parameter " << paramCount << " should "
				<< (((*i)->getAttribute()==VA_SIMPLE)? "not " : "")
				<< "be an array";
			errorHandler(errorMsg.str(), tk);
		}
		
		++paramCount;
		++j;
	}
	
	if(j!=callerParams->end()) {
		std::stringstream errorMsg;
		errorMsg << "Function '" << fEntry->getName() << "' only takes " 
			<< declParams->size() << " parameter(s)";
		errorHandler(errorMsg.str(), tk);
	}
}

/**
 * Function representing the <prg> productions
 */
void RecursiveDescentParser::prg() {
	if(errorCondition) return;
	
	if(token == TK_VOID || token == TK_INT ||
			token == TK_CHAR) 
	{
#if DEBUG_PARSER
		std::cout << "<prg> --> <functions>eoft\n";
#endif
		mainLabel = iCode.getNextLabel();
		iCode.threeAddressCode(0, TAC_CALL, mainLabel, 0);
		iCode.threeAddressCode(TAC_HALT);
		
		functions();
		match(TK_EOF);
	}
	else 
	{
		errorHandler();
	}
}

/**
 * Function representing the <functions> prods
 */
void RecursiveDescentParser::functions() {
	if(errorCondition) return;
	
	if(token == TK_VOID || token == TK_INT ||
			token == TK_CHAR) {
#if DEBUG_PARSER
		std::cout<<"<functions> --> <funct_def><functions_prime>\n";
#endif
		funct_def();
		functions_prime();
	} else {
		errorHandler();
	}
}

/**
 * Function representing the <functions_prime> productions
 */
void RecursiveDescentParser::functions_prime() {
	if(errorCondition) return;
	
	if(token == TK_VOID || 
		token == TK_INT || 
		token == TK_CHAR) 
	{
#if DEBUG_PARSER
		std::cout << "<functions_prime> --> <funct_def><functions_prime>\n";
#endif
		funct_def();
		functions_prime();
	} 
	else if(token == TK_EOF) 
	{
#if DEBUG_PARSER
		std::cout << "<functions_prime> --> e\n";
#endif
	}
	else 
	{
		errorHandler();
	}
}

/**
 * Function representing the <funct_def> productions
 */
void RecursiveDescentParser::funct_def() {
	if(errorCondition) return;
	
	if(token == TK_VOID || 
		token == TK_INT ||
		token == TK_CHAR) 
	{
#if DEBUG_PARSER
		std::cout << "<funct_def> --> <f_type><f_name>(<par_list>)<par_dec_list><comp_st>\n";
#endif
	
		Type t = f_type();
		Token name = f_name();
		
		std::string label = (name == TK_MAIN) ? mainLabel : iCode.getNextLabel();
		iCode.threeAddressCode(label);
		
		FunctionEntry* entry = new FunctionEntry();
		entry->setReturnType(t);
		entry->setLabel(label);
		
		currentReturnLabel = iCode.getNextLabel();
		
		match(TK_LEFT_PARENTHESES);
		par_list();
		match(TK_RIGHT_PARENTHESES);
		
		if(symTab.search(name)) {
			// oops a function with this name has already been declared
			std::stringstream msg;
			msg << "Duplicate function declaration '" << name.getValue() << "'";
			errorHandler(msg.str(), name);
		} else {
			symTab.insert(name, entry);
		}		
		symTab.createNewTable();
		ParamList* pList = par_dec_list();
		entry->setParameterList(pList);
		
		iCode.threeAddressCode(TAC_SAVE_RET_ADDR);
		iCode.threeAddressCode(TAC_SAVE_OLD_TOPSTK);
		iCode.threeAddressCode(TAC_SET_NEW_TOPSTK);
		
		comp_st(false); /* since we explicitely called createNewTable 
							we don't want comp_st to create another */
	
		iCode.threeAddressCode(currentReturnLabel);
		iCode.threeAddressCode(TAC_RESTORE_RET_ADDR);
		iCode.threeAddressCode(TAC_RESTORE_OLD_TOPSTK);
		iCode.threeAddressCode(TAC_GOTO_RETADDR);
	}
	else 
	{
		errorHandler();
	}
}

/**
 * Function representing the <f_name> productions
 */
Token RecursiveDescentParser::f_name() {
	Token retVal;
	if(errorCondition) return retVal;
	
	if(token == TK_IDENTIFIER || 
		token == TK_MAIN) 
	{
#if DEBUG_PARSER
		std::cout<< "<f_name> --> i | main\n";
#endif
		Token retVal = token;
		token = scanner->getToken();
		return retVal;
	}
	else 
	{
		errorHandler();
	}
	return retVal;
}

/**
 * Function representing <par_list> productions
 */
void RecursiveDescentParser::par_list() {
	if(errorCondition) return;
	
	if(token == TK_IDENTIFIER) 
	{
#if DEBUG_PARSER
		std::cout << "<par_list> --> i<par_list_prime>\n";
#endif
		
		token = scanner->getToken();
		par_list_prime();
	}
	else if(token != TK_RIGHT_PARENTHESES) 
	{
		errorHandler();
	}
}

/**
 * Function representing <par_list_prime> production
 */
void RecursiveDescentParser::par_list_prime() {
	if(errorCondition) return;
	
	if(token == TK_COMMA) 
	{
		token = scanner->getToken();
		
#if DEBUG_PARSER
		std::cout << "<par_list_prime> --> ,i<par_list>\n";
#endif
		match(TK_IDENTIFIER);
		//par_list();
		par_list_prime();
	} 
	else if(token == TK_RIGHT_PARENTHESES) 
	{
#if DEBUG_PARSER
		std::cout << "<par_list_prime> --> e\n";
#endif
	}
	else 
	{
		errorHandler();
	} 
}

/**
 * Function representing <par_dec_list> prods
 */
ParamList* RecursiveDescentParser::par_dec_list() {
	ParamList* retVal = NULL;
	if(errorCondition) return retVal;
	if(token == TK_INT || token == TK_CHAR) 
	{
#if DEBUG_PARSER
		std::cout << "<par_dec_list> --> <type><par_spec><par_dec_list_prime>;<par_dec_list>\n";
#endif
		Type t = type();
		VariableEntry* va = par_spec(t);
		
		retVal = par_dec_list_prime(t);
		retVal->push_front(va);
		
		match(TK_SEMICOLON);

		ParamList* pList = par_dec_list();
		retVal->splice(retVal->end(), *pList);
		delete(pList);
	} 
	else if(token == TK_LEFT_BRACE) 
	{
#if DEBUG_PARSER
		std::cout << "<par_dec_list> --> e\n";
#endif
		retVal = new ParamList();
	}
	else 
	{
		errorHandler();
	}
	
	return retVal;
}

/**
 * Function representing the <par_dec_list_prime> prods
 */
ParamList* RecursiveDescentParser::par_dec_list_prime(Type type) {
	ParamList* paramList = NULL;
	if(errorCondition) return paramList;
	if(token == TK_COMMA) 
	{
#if DEBUG_PARSER
		std::cout << "<par_dec_list_prime> --> ,<par_spec><par_dec_list_prime>\n";
#endif
		token = scanner->getToken();
		VariableEntry* ve = par_spec(type);
		ve->setParamFlag();
		
		if(!ve) {
			// error recovery: consume tokens until we find another comma or a semicolon
			while(token != TK_EOF) 
			{
				if(token == TK_LEFT_BRACE) {
					break;
				}
				if(token == TK_COMMA || token == TK_SEMICOLON) 
				{
					return par_dec_list_prime(type);
				} 
				token = scanner->getToken();
			}
			return new ParamList();
		}
		
		paramList = par_dec_list_prime(type);
		paramList->push_front(ve);
	} 
	else if(token == TK_SEMICOLON) 
	{
#if DEBUG_PARSER
		std::cout << "<par_dec_list_prime> --> e\n";
#endif
		paramList = new ParamList();
	}
	else 
	{	//errorHandler();
		errorHandler("missing semicolon at the end of parameter declaration", token);
	}
	
	return paramList;
}

/**
 * Function representing the <par_spec> prods
 */
VariableEntry* RecursiveDescentParser::par_spec(Type type) {
	if(errorCondition) return NULL;
	
	if(token == TK_IDENTIFIER) 
	{	
#if DEBUG_PARSER
		std::cout << "<par_spec> --> i<par_spec_prime>\n";
#endif
		Token identifier = token;	
		token = scanner->getToken();
		
		VariableAttribute va = par_spec_prime();
		VariableEntry* paramList = new VariableEntry(type, va);
	
		if(symTab.search(identifier)) {
			// duplicate parameter name
			std::stringstream errorMsg;
			errorMsg << "Duplicate declaration for parameter '" << identifier.getValue() << "'";
			errorHandler(errorMsg.str(), identifier);
		} else {
			VariableEntry* entry = new VariableEntry(
					paramList->getType(),
					paramList->getAttribute(),
					paramList->getArraySize(),
					true
			);
			
			symTab.insert(identifier, entry);
		}
		
		return paramList;
	}
	else 
	{	//errorHandler();
		errorHandler("Missing variable name in parameter declaration", token);
	}
	
	return NULL;
}

/**
 * Function representing the <par_spec_prime> prods
 */
VariableAttribute RecursiveDescentParser::par_spec_prime() {
	VariableAttribute retVal;
	retVal.attrib = VA_ERROR;
	if(errorCondition) return retVal;
	if(token == TK_LEFT_BRACKET) 
	{
		
#if DEBUG_PARSER
		std::cout << "<par_spec_prime> --> []\n";
#endif
		token = scanner->getToken();
		match(TK_RIGHT_BRACKET);
		
		retVal.attrib = VA_ARRAY;
		retVal.arraySize = 1; // arrays passed as parameters only 4 bytes
	}
	else if(token == TK_COMMA ||
			token == TK_SEMICOLON) 
	{
		
#if DEBUG_PARSER
		std::cout << "<par_spec_prime> --> e\n";
#endif
		retVal.attrib = VA_SIMPLE;
	}
	else 
	{
		errorHandler();
	}
	
	return retVal;
}

/**
 * Function representing the <f_type> prods
 */
Type RecursiveDescentParser::f_type() {
	if(errorCondition) return T_ERROR;
	if(token == TK_INT || token == TK_CHAR) 
	{
#if DEBUG_PARSER
		std::cout << "<f_type> --> <type>\n";
#endif
		return type();
	} 
	else if( token == TK_VOID) 
	{
#if DEBUG_PARSER
		std::cout << "<f_type> --> void\n";
#endif
		token = scanner->getToken();
		return T_VOID;
	}
	else 
	{
		errorHandler();
	}
	return T_ERROR;
}

/**
 * Function representing the <type> prods
 */
Type RecursiveDescentParser::type() {
	if(errorCondition) return T_ERROR;
	if(token == TK_INT) 
	{
#if DEBUG_PARSER
		std::cout << "<type> --> int\n";
#endif
		token = scanner->getToken();
		return T_INT;
	}
	else if(token == TK_CHAR) 
	{
#if DEBUG_PARSER
		std::cout << "<type> --> char\n";
#endif
		token = scanner->getToken();
		return T_CHAR;
	}
	else 
	{
		errorHandler();
	}
	return T_ERROR;
}

/**
 * Functions representing the <st> productions
 */
void RecursiveDescentParser::st() {
	if(token == TK_SEMICOLON) 
	{
#if DEBUG_PARSER
		std::cout << "<st> --> ;\n";
#endif
		token = scanner->getToken();
	} 
	else if(token == TK_LEFT_BRACE) 
	{
#if DEBUG_PARSER
		std::cout << "<st> --> <comp_st>\n";
#endif
		comp_st();
	}
	else if(token == TK_IF) 
	{
#if DEBUG_PARSER
		std::cout << "<st> --> if<log_exp><st>else<st>\n";
#endif
		token = scanner->getToken();
		
		attr logExp = log_exp();
		
		std::string lbl1 = iCode.getNextLabel();
		iCode.threeAddressCode(TAC_IF_FALSE, logExp, lbl1);

		st();
		
		std::string lbl2 = iCode.getNextLabel();
		iCode.threeAddressCode(TAC_GOTO, lbl2);
		
		match(TK_ELSE);
		
		iCode.threeAddressCode(lbl1);
		
		st();
		
		iCode.threeAddressCode(lbl2);
	} 
	else if(token == TK_WHILE) 
	{
#if DEBUG_PARSER
		std::cout << "<st> --> while<log_exp><st>\n";
#endif
		token = scanner->getToken();
		
		std::string lbl1 = iCode.getNextLabel();
		iCode.threeAddressCode(lbl1);
		std::string lbl2 = iCode.getNextLabel();
		
		attr cond = log_exp();
		
		iCode.threeAddressCode(TAC_IF_FALSE, cond, lbl2);
		
		st();
		
		iCode.threeAddressCode(TAC_GOTO, lbl1);
		iCode.threeAddressCode(lbl2);
	}
	else if(token == TK_RETURN) 
	{
#if DEBUG_PARSER
		std::cout << "<st> --> return(<exp>);\n";
#endif
		Token sToken = token;
		token = scanner->getToken();
		
		match(TK_LEFT_PARENTHESES);
		attr expAttr = exp(); 

		const FunctionEntry* fe = symTab.getCurrentFunction();
		if(expAttr.type != fe->getReturnType() && fe->getReturnType() != T_VOID) {
			std::stringstream ss;
			ss << "Type Mismatch, function '" << fe->getName() << "' must return ";
			if(fe->getReturnType() == T_INT) ss << "an integer";
			if(fe->getReturnType() == T_CHAR) ss << "a character";
			errorHandler(ss.str(), sToken);
		}
		
		match(TK_RIGHT_PARENTHESES);
		match(TK_SEMICOLON);
		iCode.threeAddressCode(TAC_SAVE_RET_VAL, expAttr);
		iCode.threeAddressCode(TAC_GOTO, currentReturnLabel);
	}
	else if(token == TK_SCANF) 
	{
#if DEBUG_PARSER
		std::cout << "<st> --> scanf<i_list>;\n";
#endif

		token = scanner->getToken();
		ParamList* pList = i_list();
		match(TK_SEMICOLON);
		
		iCode.threeAddressCode(TAC_READ, pList);
	}
	else if(token == TK_PRINTF) 
	{
#if DEBUG_PARSER
		std::cout << "<st> --> printf<o_list>;\n";
#endif

		token = scanner->getToken();
		ParamList* pList = o_list();
		match(TK_SEMICOLON);
		
		iCode.threeAddressCode(TAC_WRITE, pList);
	}
	else if(token == TK_IDENTIFIER) 
	{
#if DEBUG_PARSER
		std::cout << "<st> --> i<st_factor_ident>\n";
#endif
		TableEntry* te=NULL;
		if(!symTab.search(token, te)) {
			errorHandler("Undefined identifier", token);
		}
		token = scanner->getToken();
		st_factor_ident(te);
	}
	else if(token == TK_INT)  
	{
#if DEBUG_PARSER
		std::cout << "<st> --> int i <st_factor_type>\n";
#endif
		token = scanner->getToken();
		if(token!=TK_IDENTIFIER) {
			errorHandler();
		}		
		if(symTab.search(token) ) {
			std::stringstream msg;
			msg << "Duplicate variable declaration '" << token.getValue() << "'";
			errorHandler(msg.str(), token);
		} 
		
		VariableEntry* vEntry = new VariableEntry();
		vEntry->setType(T_INT);
		vEntry->setName( token.getValue() );
		//std::string varName = token.getValue();
		
		
		token = scanner->getToken();
		st_factor_type(vEntry);
		
		//symTab.insert(varName, vEntry);
	}
	else if(token == TK_CHAR) 
	{
#if DEBUG_PARSER
		std::cout << "<st> --> char i <st_factor_type>\n";
#endif
		token = scanner->getToken();
		if(token!=TK_IDENTIFIER) {
			errorHandler();
		}

		if(symTab.search(token)) {
			// aready declared in this scope
			std::stringstream msg;
			msg << "Duplicate variable declaration '" << token.getValue() << "'";
			errorHandler(msg.str(), token);
		}

		VariableEntry* vEntry = new VariableEntry();
		vEntry->setType(T_CHAR);
		vEntry->setName( token.getValue() );
		//std::string varName = token.getValue();
		
		token = scanner->getToken();
		st_factor_type(vEntry);
		
		//symTab.insert(varName, vEntry);
	}
	else 
	{
		errorHandler();
	}
	
	if(errorCondition) {
		while(token!=TK_EOF) {
			token = scanner->getToken();
			if(token==TK_RIGHT_BRACE) {
				errorCondition=false;
				break;
			}
			if(token==TK_SEMICOLON) {
				errorCondition=false;
				token = scanner->getToken();
				break;
			}
		}
	}
}

/**
 * Function representing the <st_prime> productions
 */
void RecursiveDescentParser::st_prime(Type type) {
	if(errorCondition) return;
	if(token == TK_COMMA) 
	{
		token = scanner->getToken();
#if DEBUG_PARSER
		std::cout << "<st_prime> --> ,i<arr_spec><st_prime>\n";
#endif
		if(token!=TK_IDENTIFIER){
			// error
		}
		
		if(symTab.search(token)) {
			std::stringstream msg;
			msg << "Duplicate variable declaration '" << token.getValue() << "'";
			errorHandler(msg.str(), token);
		}
		
		VariableEntry* entry = new VariableEntry();
		entry->setType(type);
		symTab.insert(token, entry);
		
		token = scanner->getToken();
		VariableAttribute va = arr_spec();
		entry->setAttribute(va);
		st_prime(type);
	} 
	else if(token == TK_SEMICOLON) 
	{
#if DEBUG_PARSER
		std::cout << "<st_prime> --> e\n";
#endif
	}
	else
	{
		errorHandler();
	}
}

/**
 * Function representing the <st_factor_ident> prods
 */
void RecursiveDescentParser::st_factor_ident(TableEntry* te) {
	if(errorCondition) return;
	if(token == TK_LEFT_PARENTHESES) 
	{
#if DEBUG_PARSER
		std::cout << "<st_factor_ident> --> (<o_list>);\n";
#endif
		Token leftParen = token;
		token = scanner->getToken();
		ParamList* pList = o_list();
		
		if(te) {
			if(te->getEntryType()!=TableEntry::FUNCTION) {
				std::stringstream errorMsg;
				errorMsg << "'" << te->getName() << "' is not a function";
				errorHandler(errorMsg.str(), leftParen);
			} else {
				// now makes sure the lists match
				FunctionEntry* fe = (FunctionEntry*)te;
				if(pList) matchParameters(fe, pList, leftParen);
				
				iCode.threeAddressCode(TAC_PARAM, pList);
				iCode.threeAddressCode( 
						symTab.getNextAddress(), // throw away temporary
						TAC_CALL, 
						fe->getLabel(), 
						fe->getParamCount()
					);
			}
		} else {
			std::stringstream errorMsg;
			errorMsg << "Undeclared function";
			errorHandler(errorMsg.str(), leftParen);
		}
		
		match(TK_RIGHT_PARENTHESES);
		match(TK_SEMICOLON);
	} 
	else if(token == TK_LEFT_BRACKET || 
			token == TK_ASSIGNMENT) 
	{
#if DEBUG_PARSER		
		std::cout << "<st_factor_ident> --> <var_prime>=<exp>;\n";
#endif
		VariableEntry* vEntry = (VariableEntry*)te;
		Token startToken = token;
		
		attr varAttr  = var_prime(vEntry);
		match(TK_ASSIGNMENT);
		attr expAttr = exp();
		
		if(expAttr.type != varAttr.type) {
			std::stringstream errorMsg;
			errorMsg << "Type mismatch variable '" << vEntry->getName() << "'";
			errorHandler(errorMsg.str(), startToken);
		}
		
		if(varAttr.attrib == VA_ARRAY) {
			std::stringstream errorMsg;
			errorMsg << "Assignment error, array '" << vEntry->getName() << "' must be indexed.";
			errorHandler( errorMsg.str(), startToken );
		}
		
		if(vEntry->getAttribute() == VA_ARRAY) {
			//                       array addr                           value to assign   index
			iCode.threeAddressCode(vEntry->getAttr(), TAC_ASSIGN_TO_ADDRESS_AT, expAttr, varAttr);
		} else {
			iCode.threeAddressCode(vEntry->getAttr(), TAC_ASSIGN, expAttr);
		}
		
		match(TK_SEMICOLON);
	} 
	else 
	{
		errorHandler();
	}
}

/**
 * Function representing the <st_factor_type> productions
 */
void RecursiveDescentParser::st_factor_type(VariableEntry* &vEntry) {
	if(errorCondition) return;
	if(token == TK_ASSIGNMENT) 
	{
#if DEBUG_PARSER
		std::cout << "<st_factor_type> --> =<exp>;\n";
#endif
		Token startToken = token; // keep a copy in case of error
		token = scanner->getToken();
		attr expAttr = exp();
		
		vEntry->setAttribute(VA_SIMPLE);
		symTab.insert(vEntry->getName(), vEntry);
		
		if(vEntry->getType() != expAttr.type) {
			std::stringstream errorMsg;
			errorMsg << "Type mismatch variable '" << vEntry->getName() << "'";
			errorHandler(errorMsg.str(), startToken);
		}
		
		//iCode.threeAddressCode(vEntry->getAddress(), TAC_ASSIGN, expAttr.addr );
		iCode.threeAddressCode(vEntry->getAttr(), TAC_ASSIGN, expAttr);
		
		match(TK_SEMICOLON);
	}
	else if(token == TK_LEFT_BRACKET) 
	{
#if DEBUG_PARSER
		std::cout << "<st_factor_type> --> [<st_factor_num>\n";
#endif
		token = scanner->getToken();
		st_factor_num(vEntry);
		
		symTab.insert(vEntry->getName(),  vEntry);
	}
	else if(token == TK_COMMA || 
			token == TK_SEMICOLON) 
	{
#if DEBUG_PARSER
		std::cout << "<st_factor_type> --> <st_prime>;\n";
#endif
		vEntry->setAttribute(VA_SIMPLE);
		symTab.insert(vEntry->getName(),  vEntry);
		
		st_prime(vEntry->getType());
		match(TK_SEMICOLON);
	}
	else 
	{
		errorHandler();
	}
}

/**
 * Function representing the <st_factor_num> productions
 */
void RecursiveDescentParser::st_factor_num(VariableEntry* &vEntry) {
	if(errorCondition) return;
	if(token == TK_NUM) 
	{
#if DEBUG_PARSER
		std::cout << "<st_factor_num> --> n<st_factor_right_bracket>\n";
#endif
		
		vEntry->setAttribute(
				VA_ARRAY,
				atoi(token.getValue().c_str())
		);
		
		token = scanner->getToken();
		st_factor_right_bracket( vEntry->getType() );
	} 
	else 
	{
		errorHandler();
	}
}

/**
 * Function representing <st_factor_right_bracket> prods
 */
void RecursiveDescentParser::st_factor_right_bracket(Type type) {
	if(errorCondition) return;
	if(token == TK_RIGHT_BRACKET) 
	{
#if DEBUG_PARSER
			std::cout << "<st_factor_right_bracket> --> ]<st_factor_final>\n";
#endif
			token = scanner->getToken();
			st_factor_final(type);
	}
	else
	{
		errorHandler();
	}
}

/**
 * Function represents the <st_factor_final> prods
 */
void RecursiveDescentParser::st_factor_final(Type type) {
	if(errorCondition) return;
	if(token == TK_COMMA || 
		token == TK_SEMICOLON) 
	{
#if DEBUG_PARSER
		std::cout << "<st_factor_final> --> <st_prime>;\n";
#endif
		st_prime(type);
		match(TK_SEMICOLON);
	}
	else 
	{
		errorHandler();
	}
}

/**
 * Function representing the <comp_st> production
 */
void RecursiveDescentParser::comp_st(bool createSymbolTable) {
	if(errorCondition) return;
	if(token == TK_LEFT_BRACE)
	{
#if DEBUG_PARSER
		std::cout << "<comp_st> --> {<st_list>}\n";
#endif
		token = scanner->getToken();
		if(createSymbolTable)
		{ // create a new symbols table
			symTab.createNewTable();
		} 
		st_list();
		symTab.discardCurrentTable();
		match(TK_RIGHT_BRACE);
		if(errorCondition) 
		{	//curly braces are often forgotten so just assume it's missing and continue
			errorHandler("Missing closing curly brace", token);
			errorCondition=false;
		}
	}
	else 
	{
		errorHandler("Missing openning curly brace", token, false);
	}
}

/**
 * Function representing the <st_list> productions
 */
void RecursiveDescentParser::st_list() {
	if(errorCondition) return;
	switch(token.getType()) {
		case TK_SEMICOLON:
		case TK_INT:
		case TK_CHAR:
		case TK_IDENTIFIER:
		case TK_IF:
		case TK_WHILE:
		case TK_RETURN:
		case TK_PRINTF:
		case TK_SCANF:
		case TK_LEFT_BRACE:
#if DEBUG_PARSER
			std::cout << "<st_list> --> <st><st_list_prime>\n";
#endif
			st();
			st_list_prime();
			break;
		default:
			errorHandler();
	}
}

/**
 * Function representing the <st_list_prime> productions
 */
void RecursiveDescentParser::st_list_prime() {
	if(errorCondition) return;
	switch(token.getType()) {
		case TK_SEMICOLON:
		case TK_INT:
		case TK_CHAR:
		case TK_IDENTIFIER:
		case TK_IF:
		case TK_WHILE:
		case TK_RETURN:
		case TK_PRINTF:
		case TK_SCANF:
		case TK_LEFT_BRACE:
#if DEBUG_PARSER
			std::cout << "<st_list_prime> --> <st_list>\n";
#endif
			st_list();
			break;
		case TK_RIGHT_BRACE:
#if DEBUG_PARSER
			std::cout << "<st_list_prime> --> e\n";
#endif
			break;
		default:
			errorHandler();
	}
}

/**
 * Function representing the <arr_spec> productions
 */
VariableAttribute RecursiveDescentParser::arr_spec() {
	VariableAttribute retVal;
	retVal.attrib = VA_ERROR;
	if(errorCondition) return retVal;
	if(token == TK_LEFT_BRACKET) 
	{
#if DEBUG_PARSER
		std::cout << "<arr_spec> --> [n]\n";
#endif
		token = scanner->getToken();
		if(token==TK_NUM) {
			retVal.arraySize = atoi(token.getValue().c_str());
		} else {
			errorHandler("Missing array size in declaration", token);
		}
		token = scanner->getToken();
		match(TK_RIGHT_BRACKET);
		retVal.attrib = VA_ARRAY;
	}
	else if(token == TK_COMMA || 
			token == TK_SEMICOLON) 
	{
#if DEBUG_PARSER
		std::cout << "<arr_spec> --> e\n";
#endif
		retVal.attrib = VA_SIMPLE;
	}
	else
	{
		errorHandler();
	}
	
	return retVal;
}

/**
 * Function representing the <var> productions
 */
VariableEntry* RecursiveDescentParser::var() {
	VariableEntry* ve=NULL;
	
	if(errorCondition) return ve;
	
	if(token == TK_IDENTIFIER) 
	{
#if DEBUG_PARSER
		std::cout << "<var> --> i<var_prime>\n";
#endif
		TableEntry* te=NULL;
		if(!symTab.search(token, te)) 
		{			
			std::stringstream errorMsg;
			errorMsg << "Undeclared variable '" << token.getValue() << "'";
			errorHandler(errorMsg.str(), token);
		} 
		
		if(te && te->getEntryType()==TableEntry::VARIABLE) 
		{
			ve = (VariableEntry*)te;
 		}
		
		token = scanner->getToken();
		attr varP = var_prime(ve);
		
		if(ve && ve->getAttribute() == VA_ARRAY && varP.attrib == VA_SIMPLE) {
			VariableEntry* vEntry = new VariableEntry(ve->getType(), VA_SIMPLE);
			vEntry->setAddress( symTab.getNextAddress() );
			
			iCode.threeAddressCode(vEntry->getAttr(), TAC_ADDRESS_OF, ve->getAttr(), varP);
			ve = vEntry;
		}
	} 
	else 
	{
		errorHandler();
	}
	
	return ve;
}

/**
 * Function representing the <var_prime> productions
 */
attr RecursiveDescentParser::var_prime(VariableEntry* entry) {
	attr retval;
	retval.type = T_ERROR;
	
	if(errorCondition) return retval;
	if(token == TK_LEFT_BRACKET) 
	{
#if DEBUG_PARSER
		std::cout << "<var_prime> --> [<exp>]\n";
#endif
		// make sure this was declared as an array
		if(entry && entry->getAttribute()!=VA_ARRAY) {
			std::stringstream errorMsg;
			errorMsg << entry->getName() << " not declared as array";
			errorHandler(errorMsg.str(), token);
		}
				
		token = scanner->getToken();
		attr expAttr = exp();
		
		// since the array is indexed it should be assigned VA_SIMPLE
		retval.attrib = VA_SIMPLE;
		retval.type = entry->getType();
		retval.addr = expAttr.addr;
		
		match(TK_RIGHT_BRACKET);
	}
	else if(token == TK_ASSIGNMENT || 
			token == TK_COMMA ||
			token == TK_SEMICOLON || 
			token == TK_RIGHT_PARENTHESES) 
	{
#if DEBUG_PARSER
		std::cout << "<var_prime> --> e\n";
#endif
		if(entry) {
			retval = entry->getAttr();
		}
	}
	else 
	{
		errorHandler();
	}
	
	return retval;
}

/**
 * Function representing the <log_exp> productions
 */
attr RecursiveDescentParser::log_exp() {
	attr retVal;
	
	if(errorCondition) return retVal;
	if(token == TK_LEFT_PARENTHESES) 
	{
#if DEBUG_PARSER
		std::cout << "<log_exp> --> <log_term><log_exp_prime>\n";
#endif
		attr logTerm = log_term();
		retVal = log_exp_prime( logTerm );
	}
	else 
	{
		errorHandler();
	}
	
	return retVal;
}

/**
 * Function representing the <log_exp_prime> productions
 */
attr RecursiveDescentParser::log_exp_prime(attr lhs) {
	attr retVal, rhs, logTerm;
	
	if(errorCondition) return retVal;
	switch(token.getType()) {
		case TK_LOGIC_OR:
#if DEBUG_PARSER
			std::cout << "<log_exp_prime> --> ||<log_term><log_exp_prime>\n";
#endif
			token = scanner->getToken();
			logTerm = log_term();
			rhs = log_exp_prime(logTerm);
			
			retVal.addr = symTab.getNextAddress();
			iCode.threeAddressCode(retVal, TAC_OR, lhs, rhs);
			
			break;	
		case TK_RIGHT_PARENTHESES:
		case TK_SEMICOLON:
		case TK_INT:
		case TK_CHAR:
		case TK_IDENTIFIER:
		case TK_IF:
		case TK_WHILE:
		case TK_RETURN:
		case TK_PRINTF:
		case TK_SCANF:
		case TK_LEFT_BRACE:
#if DEBUG_PARSER
			std::cout << "<log_exp_prime> --> e\n";
#endif
			retVal = lhs;
			break;
		default:
			errorHandler();
	}
	
	return retVal;
}

/**
 * Function representing the <log_term> productions
 */
attr RecursiveDescentParser::log_term() {
	attr retVal, lhs;
	
	if(errorCondition) return retVal;
	if(token == TK_LEFT_PARENTHESES) {
#if DEBUG_PARSER
		std::cout << "<log_term> --> <log_prim><log_term_prime>\n";
#endif
		lhs = log_prim();
		retVal = log_term_prime( lhs );
	} else {
		errorHandler();
	}
	
	return retVal;
}

/**
 * Function representing the <log_term_prime> productions
 */
attr RecursiveDescentParser::log_term_prime(attr lhs) {
	attr retVal, rhs, logPrim;
	
	if(errorCondition) return retVal;
	if(token == TK_LOGIC_AND) 
	{
#if DEBUG_PARSER
		std::cout << "<log_term_prime> --> &&<log_prim><log_term_prime>\n";
#endif
		Token sToken = token;
		token = scanner->getToken();
		
		logPrim = log_prim();
		rhs = log_term_prime( logPrim );
		
		retVal.addr = symTab.getNextAddress();
		iCode.threeAddressCode(retVal, TAC_AND, lhs, rhs);
		
	}
	else if(token == TK_LOGIC_OR ||
			token == TK_RIGHT_PARENTHESES ||
			token == TK_SEMICOLON ||
			token == TK_INT ||
			token == TK_CHAR ||
			token == TK_IDENTIFIER ||
			token == TK_IF ||
			token == TK_WHILE ||
			token == TK_RETURN ||
			token == TK_PRINTF ||
			token == TK_SCANF ||
			token == TK_LEFT_BRACE)
	{
#if DEBUG_PARSER
		std::cout << "<log_term_prime> --> e\n";
#endif
		retVal = lhs;
	}	
	else
	{
		errorHandler();
	}
	
	return retVal;
}

/**
 * Function representing the <log_prim> productions
 */
attr RecursiveDescentParser::log_prim() {
	attr retVal;
	
	if(errorCondition) return retVal;
	if(token == TK_LEFT_PARENTHESES) {
#if DEBUG_PARSER
		std::cout << "<log_prim> --> (<log_prim_prime>\n";
#endif
		token = scanner->getToken();
		retVal = log_prim_prime();
	} else {
		errorHandler();
	}
	
	return retVal;
}

/**
 * Function representing the <log_prim_prime> productions
 */
attr RecursiveDescentParser::log_prim_prime() {
	OpCode opCode;
	attr retVal, lhs, rhs;
	
	if(errorCondition) return retVal;
	if(token == TK_IDENTIFIER ||
			token == TK_NUM ||
			token == TK_CHAR_CONST ||
			token == TK_LEFT_PARENTHESES)
	{
#if DEBUG_PARSER
		std::cout << "<log_prim_prime> --> <exp><relop><exp>)\n";
#endif
		Token sToken = token;
		lhs = exp();
		opCode = rel_op();
		rhs = exp();
		
		if(lhs.attrib == VA_ARRAY || rhs.attrib == VA_ARRAY) {
			errorHandler("Comparison error, array must be indexed", sToken);
		}
		
		if(lhs.type != rhs.type) {
			errorHandler("Comparison error, types must match.", sToken);
		}
		
		retVal.addr = symTab.getNextAddress();
		iCode.threeAddressCode(retVal, opCode, lhs, rhs);
		
		match(TK_RIGHT_PARENTHESES);
	}
	else if(token == TK_EXCLAMATION) 
	{
#if DEBUG_PARSER
		std::cout << "<log_prim_prime> --> !<log_exp>)\n";
#endif
		Token sToken = token;
		token = scanner->getToken();
		
		lhs = log_exp();
		
		if(lhs.attrib == VA_ARRAY) {
			errorHandler("Comparison error, unary not cannot be applied to an array", sToken);
		}
		
		retVal.addr = symTab.getNextAddress();
		iCode.threeAddressCode(retVal, TAC_NOT, lhs);
		
		match(TK_RIGHT_PARENTHESES);
	}
	else
	{
		errorHandler();
	}
	
	return retVal;
}

/**
 * Function representing the <rel_op> productions
 */
OpCode RecursiveDescentParser::rel_op() {
	OpCode opCode = TAC_ERROR;
	
	if(errorCondition) return opCode;
	switch(token.getType()) {
	case TK_LT:
		opCode = TAC_LT;
#if DEBUG_PARSER
		std::cout << "<rel_op> --> <\n";
#endif
		token = scanner->getToken();
		break;
	case TK_GT:
		opCode = TAC_GT;
#if DEBUG_PARSER
		std::cout << "<rel_op> --> >\n";
#endif
		token = scanner->getToken();
		break;
	case TK_EQUAL:
		opCode = TAC_EQ;
#if DEBUG_PARSER
		std::cout << "<rel_op> --> ==\n";
#endif
		token = scanner->getToken();
		break;
	case TK_LTE:
		opCode = TAC_LTE;
#if DEBUG_PARSER
		std::cout << "<rel_op> --> <=\n";
#endif
		token = scanner->getToken();
		break;
	case TK_GTE:
		opCode = TAC_GTE;
#if DEBUG_PARSER
		std::cout << "<rel_op> --> >=\n";
#endif
		token = scanner->getToken();
		break;
	case TK_NOT_EQ:
		opCode = TAC_NOT_EQ;
#if DEBUG_PARSER
		std::cout << "<rel_op> --> !=\n";
#endif
		token = scanner->getToken();
		break;
	default:
		errorHandler();
	}
	
	return opCode;
}

/**
 * Function representing the <exp> productions
 */
attr RecursiveDescentParser::exp() {
	attr retVal, lhs, rhs;
	retVal.type = T_ERROR;
	
	if(errorCondition) return retVal;
	
	switch(token.getType()) {
	case TK_IDENTIFIER:
	case TK_NUM:
	case TK_CHAR_CONST:
	case TK_LEFT_PARENTHESES:
#if DEBUG_PARSER
		std::cout << "<exp> --> <term><exp_prime>\n";
#endif
		lhs = term();
		rhs = exp_prime( lhs );

		//retVal = lhs;
		retVal = rhs;
		
		if(rhs.type != lhs.type)
		{
			//TODO change this error msg
			errorHandler("Type mismatch, cannot convert from int to char", token);
		}
		
		break;
	default:
		errorHandler();
	}
	
	return retVal;
}

/**
 * Function representing the <exp_prime> productions
 */
attr RecursiveDescentParser::exp_prime(attr lhs) {
	OpCode opCode;
	attr retVal, termAttr, rhs;
	retVal.type = T_ERROR;

	if(errorCondition) return retVal;
	if(token == TK_PLUS || 
			token == TK_MINUS) 
	{
#if DEBUG_PARSER
			std::cout << "<exp_prime> --> <add_op><term><exp_prime>\n";
#endif
			Token sToken = token;
			opCode = add_op();
			termAttr = term();
			rhs = exp_prime( termAttr );
			
			retVal.type = lhs.type;
			retVal.addr = symTab.getNextAddress(); // create a temp
			iCode.threeAddressCode(retVal, opCode, lhs, rhs);
			
			if(lhs.type != rhs.type)
			{
				errorHandler("Type mismatch (exp_prime)", sToken);
			}
	}
	else if(token == TK_RIGHT_PARENTHESES ||
			token == TK_RIGHT_BRACKET ||
			token == TK_SEMICOLON ||
			token == TK_LT ||
			token == TK_GT ||
			token == TK_EQUAL ||
			token == TK_LTE ||
			token == TK_GTE ||
			token == TK_NOT_EQ)
	{
#if DEBUG_PARSER
			std::cout << "<exp_prime> --> e\n";
#endif
			retVal = lhs;
			//retVal.param = false;
	}
	else
	{
			errorHandler();
	}
	
	return retVal;
}

/**
 * Function representing the <term> productions
 */
attr RecursiveDescentParser::term() {
	attr retVal, lhs, rhs;
	retVal.type = T_ERROR;
	
	if(errorCondition) return retVal;
	
	switch(token.getType()) {
	case TK_IDENTIFIER:
	case TK_NUM:
	case TK_CHAR_CONST:
	case TK_LEFT_PARENTHESES:
#if DEBUG_PARSER
		std::cout << "<term> --> <prim><term_prime>\n";
#endif
		
		lhs = prim();
		rhs = term_prime( lhs );
		
		//retVal = lhs;
		retVal = rhs;
		
		if(lhs.attrib == VA_ARRAY) {
			errorHandler("array must be indexed", token);
		}
	
		if(lhs.type != rhs.type) {
			errorHandler("Type mismatch, cannot convert from int to char (term)", token);
		}
		
		break;
	default:
		errorHandler();
	}
	
	return retVal;
}

/**
 * Function representing the <term_prime> productions
 */
attr RecursiveDescentParser::term_prime( attr lhs ) {
	attr retVal, primP, rhs;
	OpCode opCode;
	retVal.type = T_ERROR;	
	Token startToken = token;

	if(errorCondition) return retVal;
	
	switch(token.getType()) {
	case TK_ASTERISK:
	case TK_SLASH:
	case TK_PERCENT:
#if DEBUG_PARSER
		std::cout << "<term_prime> --> <mult_op><prim><term_prime>\n";
#endif
		
		opCode = mult_op();
		primP = prim();
		rhs = term_prime( primP );
		
		retVal = lhs;
		retVal.addr = symTab.getNextAddress(); 
		//iCode.threeAddressCode(retVal.addr, opCode, lhs.addr, rhs.addr);
		iCode.threeAddressCode(retVal, opCode, lhs, rhs);
		
		if(rhs.attrib == VA_ARRAY || lhs.attrib == VA_ARRAY) {
			errorHandler("Arithmetic operation error, array must be indexed.", startToken);
		}
		
		if(rhs.type != lhs.type) {
			errorHandler("Type mismatch, cannot convert from int to char (term_prime) ", startToken);
		}
		
		break;
	case TK_PLUS:
	case TK_MINUS:
	case TK_RIGHT_PARENTHESES:
	case TK_RIGHT_BRACKET:
	case TK_SEMICOLON:
	case TK_LT:
	case TK_GT:
	case TK_LTE:
	case TK_GTE:
	case TK_EQUAL:
	case TK_NOT_EQ:
#if DEBUG_PARSER
		std::cout << "<term_prime> --> e\n";
#endif
		retVal = lhs;
		break;
	default:
		errorHandler();
	}
	
	return retVal;
}

/**
 * Function representing the <prim> productions
 */
attr RecursiveDescentParser::prim() {
	attr retVal, ident, primP;
	retVal.type = T_ERROR;
	
	if(errorCondition) return retVal;
	
	if(token == TK_IDENTIFIER) 
	{
#if DEBUG_PARSER
		std::cout << "<prim> --> i<prim_prime>\n";
#endif
		TableEntry* tEntry;
		if(!symTab.search(token, tEntry)) {
			std::stringstream ss;
			ss << "Unknown identifier " << token.getValue(); 
			errorHandler(ss.str(), token);
			errorCondition = true;
			return retVal;
		} else {
			retVal = ident = tEntry->getAttr();
		}
		token = scanner->getToken();
		primP = prim_prime( tEntry );

		if(ident.attrib == VA_ARRAY && primP.attrib == VA_SIMPLE)
		{
			retVal.addr = symTab.getNextAddress();
			retVal.attrib = VA_SIMPLE;
			retVal.param = false; // weird
			iCode.threeAddressCode(retVal, TAC_ADDRESS_OF, ident, primP );
		}
		else if(tEntry->getEntryType()==TableEntry::FUNCTION) {
			retVal.addr = primP.addr;
		}
	} 
	else if(token == TK_NUM) 
	{
#if DEBUG_PARSER
		std::cout << "<prim> --> n\n";
#endif
		retVal.addr = symTab.getNextAddress();
		retVal.attrib = VA_SIMPLE;
		retVal.type = T_INT;
		
		std::string val = token.getValue();
		int litTabIndex = litTab.insert(atoi(val.c_str()));
		iCode.threeAddressCode(retVal, TAC_NUM_CONST, litTabIndex);
		
		token = scanner->getToken();
	}
	else if(token == TK_CHAR_CONST) 
	{
#if DEBUG_PARSER
		std::cout << "<prim> --> 'c'\n";
#endif
		retVal.addr = symTab.getNextAddress();
		retVal.attrib = VA_SIMPLE;
		retVal.type = T_CHAR;
		
		std::string val = token.getValue();
		int litTabIndex = litTab.insert(val[1]);
		iCode.threeAddressCode(retVal, TAC_CHAR_CONST, litTabIndex);
		
		token = scanner->getToken();		
	}
	else if(token == TK_LEFT_PARENTHESES) 
	{
#if DEBUG_PARSER
		std::cout << "<prim> --> (<exp>)\n";
#endif
		token = scanner->getToken();
		retVal = exp();
		match(TK_RIGHT_PARENTHESES);
	}
	else
	{
		errorHandler();
	}
	
	return retVal;
}

/**
 * Function representing the <prim_prime> productions
 */
attr RecursiveDescentParser::prim_prime(TableEntry* pTabEntry) {
	attr retval;
	retval.type = T_ERROR;
	
	if(errorCondition) return retval;
	if(token == TK_LEFT_BRACKET) 
	{
#if DEBUG_PARSER
		std::cout << "<prim_prime> --> [<exp>]\n";
#endif
		token = scanner->getToken();
		
		retval = exp();
		retval.attrib = VA_SIMPLE;
		
		match(TK_RIGHT_BRACKET);
	}
	else if(token == TK_LEFT_PARENTHESES)
	{
#if DEBUG_PARSER
		std::cout << "<prim_prime> --> (<o_list>)\n";
#endif
		Token sToken = token;
		token = scanner->getToken();
		ParamList* pList = o_list();
		match(TK_RIGHT_PARENTHESES);

		if(pTabEntry && pTabEntry->getEntryType()==TableEntry::FUNCTION) {
			FunctionEntry* fe = (FunctionEntry*)pTabEntry;
			if(pList) {
				matchParameters(fe, pList, sToken);
			}
			retval.type = fe->getReturnType();
			retval.addr = symTab.getNextAddress();

			iCode.threeAddressCode(TAC_PARAM, pList);
			iCode.threeAddressCode(retval, TAC_CALL, fe->getLabel(), fe->getParamCount());
		}
		else {
			std::stringstream errorMsg;
			errorMsg << "'" << pTabEntry->getName() << "' is not a function";
			errorHandler(errorMsg.str(), sToken);
		}
	}
	else if( token == TK_ASTERISK || 
			token == TK_SLASH || 
			token == TK_PERCENT || 
			token == TK_PLUS ||
			token == TK_MINUS || 
			token == TK_RIGHT_PARENTHESES || 
			token == TK_RIGHT_BRACKET || 
			token == TK_SEMICOLON || 
			token == TK_LT || 
			token == TK_GT || 
			token == TK_LTE || 
			token == TK_GTE || 
			token == TK_EQUAL || 
			token == TK_NOT_EQ ) 
	{		
#if DEBUG_PARSER
		std::cout << "<prim_prime> --> e\n";
#endif
		retval = pTabEntry->getAttr();
	}
	else {
		errorHandler();
	}
	
	return retval;
}

/**
 * Function representing the <add_op> productions
 */
OpCode RecursiveDescentParser::add_op() {
	OpCode opCode = TAC_ERROR;
	if(errorCondition) return opCode;
	if(token == TK_PLUS) 
	{
#if DEBUG_PARSER
		std::cout << "<add_op> --> + \n";
#endif
		opCode = TAC_PLUS;
		token = scanner->getToken();
	}
	else if(token == TK_MINUS) 
	{
#if DEBUG_PARSER
		std::cout << "<add_op> --> -\n";
#endif
		opCode = TAC_MINUS;
		token = scanner->getToken();
	}
	else 
	{
		errorHandler();
	}
	
	return opCode;
}

/**
 * Function representing the <mult_op> productions
 */
OpCode RecursiveDescentParser::mult_op() {
	OpCode opCode = TAC_ERROR;
	if(errorCondition) return opCode;
	if(token == TK_ASTERISK) {
#if DEBUG_PARSER
		std::cout << "<mult_op> --> *\n";
#endif
		opCode = TAC_MULT;
		token = scanner->getToken();
	} else 	if(token == TK_SLASH) {
#if DEBUG_PARSER
		std::cout << "<mult_op> --> /\n";
#endif
		opCode = TAC_DIV;
		token = scanner->getToken();
	} else if(token == TK_PERCENT) {
#if DEBUG_PARSER
		std::cout << "<mult_op> --> %\n";
#endif
		opCode = TAC_MOD;
		token = scanner->getToken();
	} else {
		errorHandler();
	}
	
	return opCode;
}

/**
 * Function representing the <i_list> productions
 */
ParamList* RecursiveDescentParser::i_list() {
	ParamList* pList = NULL;
	if(errorCondition) return pList;
	if(token == TK_IDENTIFIER) {
#if DEBUG_PARSER
		std::cout << "<i_list> --> <var><i_list_prime>\n";
#endif
		VariableEntry* ve = var();
		pList = i_list_prime();
		pList->push_front(ve);
	} 
	else 
	{
		errorHandler();
	}
	return pList;
}

/**
 * Function representing the <i_list_prime> productions
 */
ParamList* RecursiveDescentParser::i_list_prime() {
	ParamList* pList = NULL;
	
	if(errorCondition) return pList;
	if(token == TK_COMMA) 
	{
#if DEBUG_PARSER
		std::cout << "<i_list_prime> --> ,<var><i_list_prime>\n";
#endif
		token = scanner->getToken();
		VariableEntry* ve = var();
		pList = i_list_prime();
		pList->push_front(ve);
	} 
	else if(token == TK_SEMICOLON) 
	{
#if DEBUG_PARSER
		std::cout << "<i_list_prime> --> e\n";
#endif
		pList = new ParamList();
	}
	else 
	{
		errorHandler();
	}
	return pList;
}

/**
 * Function representing the <o_list> productions
 */
ParamList* RecursiveDescentParser::o_list() {
	ParamList* pList = NULL;
	
	if(errorCondition) return pList;
	
	if(token == TK_IDENTIFIER || token == TK_NUM ||
			token == TK_CHAR_CONST) 
	{
#if DEBUG_PARSER
		std::cout << "<o_list> --> <oelem><o_list_prime>\n";
#endif
		pList = new ParamList();
		
		attr elemAttr = oelem(pList);
		/* delay the genration of TAC until we know it's a 
		 * function call, might just be printf
		iCode.threeAddressCode(TAC_PARAM, elemAttr.addr);
		*/
		o_list_prime(pList);		
	}
	else
	{
		errorHandler();
	}
	
	return pList;
}

/**
 * Function representing the <o_list_prime> productions
 */
void RecursiveDescentParser::o_list_prime(ParamList* &pList) {
	if(errorCondition) return;
	if(token == TK_COMMA) 
	{
#if DEBUG_PARSER
		std::cout << "<o_list_prime> --> ,<oelem><o_list_prime>\n";
#endif
		token = scanner->getToken();
		
		attr elemAttr = oelem(pList);
		/* delay the genration of TAC until we know it's a 
		 * function call, might just be printf
		iCode.threeAddressCode(TAC_PARAM, elemAttr.addr);
		*/
		o_list_prime(pList);
	}
	else if(token == TK_RIGHT_PARENTHESES || token == TK_SEMICOLON) 
	{
#if DEBUG_PARSER
		std::cout << "<o_list_prime> --> e\n";
#endif
	}
	else 
	{
		errorHandler();
	}
}

/**
 * Function representing the <oelem> productions
 */
attr RecursiveDescentParser::oelem(ParamList* &pList) {
	attr retVal;
	retVal.type = T_ERROR;
	VariableEntry* vEntry = NULL;
	
	if(errorCondition) return retVal;
	
	if(token == TK_IDENTIFIER)
	{
#if DEBUG_PARSER
		std::cout << "<oelem> --> <var>\n";
#endif
		vEntry = var();
	}
	else if(token == TK_NUM) 
	{
#if DEBUG_PARSER
		std::cout << "<oelem> --> n\n";
#endif
		//TODO fix memory leak here vEntry is never deleted
		vEntry = new VariableEntry(T_INT, VA_SIMPLE);
		vEntry->setAddress( symTab.getNextAddress() );
		
		std::string val = token.getValue();
		int litTabIndex = litTab.insert(atoi(val.c_str()));
		iCode.threeAddressCode(vEntry->getAttr(), TAC_NUM_CONST, litTabIndex);
		
		token = scanner->getToken();
	} 
	else if(token == TK_CHAR_CONST) 
	{
#if DEBUG_PARSER
		std::cout << "<oelem> --> 'c'\n";
#endif
		//TODO fix memory leak here vEntry is never deleted
		vEntry = new VariableEntry(T_CHAR, VA_SIMPLE);
		vEntry->setAddress( symTab.getNextAddress() );
		
		std::string val = token.getValue();
		int litTabIndex = litTab.insert(val[1]);
		iCode.threeAddressCode(vEntry->getAttr(), TAC_CHAR_CONST, litTabIndex);
		
		token = scanner->getToken();
	}
	else 
	{
		errorHandler();
	}
	
	if(vEntry) {
		pList->push_back(vEntry);
		retVal = vEntry->getAttr();
	}
	
	return retVal;
}

void RecursiveDescentParser::registerObserver(ErrorObserver* o) {
	errorObservers.push_back(o);
}

void RecursiveDescentParser::notifyErrorObservers(std::string errorMsg) {
	for(std::vector<ErrorObserver*>::iterator i=errorObservers.begin();
		i!=errorObservers.end();
		++i)
	{
		(*i)->updateError(errorMsg);
	}
}

void RecursiveDescentParser::removeObserver(ErrorObserver* o) {
	for(std::vector<ErrorObserver*>::iterator i=errorObservers.begin();
		i!=errorObservers.end();
		++i)
	{
		if((*i) == o) {
			errorObservers.erase(i);
			return;
		}
	}
}